package main

import (
	"fmt"
	"sync"
	"sync/atomic"
	"time"
)

func test1() {
	for i := 0; i < 10; i++ {
		go func() {
			fmt.Print(i, " ")
		}()
	}
	// 大概率没有任何输出
}

func test2() {
	for i := 0; i < 10; i++ {
		go func() {
			fmt.Print(i, " ")
		}()
	}
	time.Sleep(time.Millisecond * 500) //小睡500毫秒
}

func test3() {
	for i := 0; i < 10; i++ {
		go func(i int) {
			//time.Sleep(time.Second * 1)
			fmt.Print(i, " ")
		}(i)
	}
	time.Sleep(time.Millisecond * 500)
	// 输出: 9 3 4 5 6 7 8 0 2 1 (顺序不确定)
}

func test4() {
	num := 10
	sign := make(chan struct{}, num)

	for i := 0; i < num; i++ {
		go func(i int) {
			fmt.Print(i, " ")
			sign <- struct{}{}
		}(i)
	}

	for j := 0; j < num; j++ {
		<-sign
	}
}

func test5() {
	var count uint32
	trigger := func(i uint32, fn func()) {
		for {
			if n := atomic.LoadUint32(&count); n == i {
				fn()
				atomic.AddUint32(&count, 1)
				break
			}
			time.Sleep(time.Nanosecond)
		}
	}
	for i := uint32(0); i < 10; i++ {
		go func(i uint32) {
			fn := func() {
				fmt.Print(i, " ")
			}
			trigger(i, fn)
		}(i)
	}
	trigger(10, func() {})

	//输出: 0 1 2 3 4 5 6 7 8 9
}

// 使用 sync.WaitGroup
func test6() {
	var wg sync.WaitGroup
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(i int) {
			fmt.Print(i, " ")
			wg.Done()
		}(i)
	}
	wg.Wait()
	// 输出: 9 6 4 1 2 7 0 8 5 3 (顺序不确定)
}

func main() {
	//test1()
	//test2()
	//test3()
	//test4()
	//test5()
	test6()
}
